package com.project.springboot.handler;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.gitee.yongzhuzl.commonutil.util.ExceptionUtil;
import com.gitee.yongzhuzl.commonutil.util.result.ResponseResult;
import com.project.springboot.exception.ResponseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.NoHandlerFoundException;
import redis.clients.jedis.exceptions.JedisConnectionException;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;

/**
 * description: 全局异常处理器
 * @author 朱正磊
 * @date 2019-08-29 10:42:11
 */
@Slf4j
@ControllerAdvice
public class MyExceptionHandler {

    /**
     * description: 拦截系统自定义异常
     * @author 朱正磊
     * @date 2023-08-28 13:31:43
     * @param e 系统自定义异常对象
     * @return 返回响应结果对象
     */
    @ExceptionHandler(ResponseException.class)
    @ResponseBody
    public ResponseResult<Void> handleResponseException(ResponseException e) {
        log.error("发生系统自定义异常，异常信息：", e);
        return ResponseResult.buildResult(e.getCode(), e.getMessage());
    }

    /**
     * description: 拦截未知的运行时异常
     * @author 朱正磊
     * @date 2023-08-28 13:32:33
     * @param e 运行时异常对象
     * @return 返回响应结果对象
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public ResponseResult<Void> handleRuntimeException(RuntimeException e) {
        log.error("发生未知运行时异常：类===》{}，原因===》{}，大概信息===》{}，具体信息===》{}",
                e.getClass(), e.getCause(), e.getMessage(), ExceptionUtil.logExceptionStack(e));
        if (e instanceof NullPointerException) {
            return ResponseResult.buildError("空指针引用异常！");
        } else if (e instanceof ClassCastException) {
            return ResponseResult.buildError("类型强制转换异常！");
        } else if (e instanceof NumberFormatException) {
            return ResponseResult.buildError("数字格式异常！");
        } else if (e instanceof IllegalArgumentException) {
            return ResponseResult.buildError("传递非法参数异常！");
        } else if (e instanceof ArithmeticException) {
            return ResponseResult.buildError("算术运算异常！");
        } else if (e instanceof ArrayStoreException) {
            return ResponseResult.buildError("向数组中存放与声明类型不兼容对象异常！");
        } else if (e instanceof IndexOutOfBoundsException) {
            return ResponseResult.buildError("下标越界异常！");
        } else if (e instanceof NegativeArraySizeException) {
            return ResponseResult.buildError("创建一个大小为负数的数组错误异常！");
        } else if (e instanceof SecurityException) {
            return ResponseResult.buildError("安全异常！");
        } else if (e instanceof UnsupportedOperationException) {
            return ResponseResult.buildError("不支持的操作异常！");
        } else if (e instanceof CannotCreateTransactionException) {
            return ResponseResult.buildError("数据库服务获取连接中断！");
        } else if (e instanceof MyBatisSystemException) {
            Throwable cause = e.getCause();
            if (cause instanceof TooManyResultsException) {
                log.info("异常根源信息1：{}", cause.getMessage());
                return ResponseResult.buildError("查询结果最多应该只有一条，但是却查出多条！");
            }
        } else if (e instanceof SerializationException) {
            Throwable cause = e.getCause();
            if (cause instanceof JsonMappingException) {
                log.info("异常根源信息2：{}", cause.getMessage());
                return ResponseResult.buildError("获取redis缓存映射失败！");
            }
        } else if (e instanceof JedisConnectionException) {
            return ResponseResult.buildError("获取redis服务连接遭到拒绝！");
        } else if (e instanceof DuplicateKeyException) {
            return ResponseResult.buildError("数据库表主键重复异常！");
        } else if (e instanceof BadSqlGrammarException) {
            return ResponseResult.buildError("SQL语法错误异常！");
        }
        return ResponseResult.buildError("服务器抛出未知异常！请速速联系后台开发人员！");
    }

    /**
     * description: 拦截未知的非运行时异常
     * @author 朱正磊
     * @date 2023-08-28 13:33:24
     * @param e 非运行时异常对象
     * @return 返回响应结果对象
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult<Void> defaultErrorHandler(Exception e) {
        log.error("发生未知非运行时异常：类===》{}，原因===》{}，大概信息===》{}，具体信息===》{}",
                e.getClass(), e.getCause(), e.getMessage(), ExceptionUtil.logExceptionStack(e));
        if (e instanceof NoSuchMethodException) {
            return ResponseResult.buildError("方法未找到异常！");
        } else if (e instanceof FileNotFoundException) {
            return ResponseResult.buildError("文件未找到异常！");
        } else if (e instanceof SQLException) {
            return ResponseResult.buildError("操作数据库异常！");
        } else if (e instanceof ClassNotFoundException) {
            return ResponseResult.buildError("类文件未找到异常！");
        } else if (e instanceof IOException) {
            return ResponseResult.buildError("输入输出异常！");
        } else if (e instanceof HttpMediaTypeNotSupportedException) {
            return ResponseResult.buildError("客户端请求参数格式错误！");
        } else if (e instanceof MissingServletRequestParameterException) {
            return ResponseResult.buildError("请求参数缺失！");
        } else if (e instanceof NoHandlerFoundException) {
            return ResponseResult.buildError("找不到对应资源！");
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            return ResponseResult.buildError("HTTP请求方法不支持！");
        }
        return ResponseResult.buildError("服务器发生未知异常！请尽快联系后台开发人员！");
    }

}
